PyVista 中的点和数组

有多种方法在 PyVista 中创建点,本节展示如何高效创建点数组:

PyVista 为所有三种方法提供 Python 化方法,因此您可以选择对您最高效的方法。如果您熟悉 VTK API,可以选择包装 VTK 数组,但您可能会发现使用 numpy.ndarray 更方便,并避免了 Python 中的循环开销。

包装 VTK 数组

让我们定义三角形的点。使用 VTK API,可以这样做:

code.matlab
>>> import vtk
>>> vtk_array = vtk.vtkDoubleArray()
>>> vtk_array.SetNumberOfComponents(3)
>>> vtk_array.SetNumberOfValues(9)
>>> vtk_array.SetValue(0, 0)
>>> vtk_array.SetValue(1, 0)
>>> vtk_array.SetValue(2, 0)
>>> vtk_array.SetValue(3, 1)
>>> vtk_array.SetValue(4, 0)
>>> vtk_array.SetValue(5, 0)
>>> vtk_array.SetValue(6, 0.5)
>>> vtk_array.SetValue(7, 0.667)
>>> vtk_array.SetValue(8, 0)
>>> print(vtk_array)
vtkDoubleArray(0x55f3d208bac0)
  Debug: Off
  Modified Time: 83
  Reference Count: 1
  Registered Events: (none)
  Name: (none)
  Data type: double
  Size: 9
  MaxId: 8
  NumberOfComponents: 3
  Information: 0
  Name: (none)
  Number Of Components: 3
  Number Of Tuples: 3
  Size: 9
  MaxId: 8
  LookupTable: (none)

PyVista 支持直接从 vtkDataArray 类创建对象,但有一个更好且更 Python 化的替代方案,即使用 numpy.ndarray。

在 PyVista 中使用 NumPy

您可以使用 NumPy 创建点数组:

code.matlab
>>> import numpy as np
>>> np_points = np.array([[0, 0, 0], [1, 0, 0], [0.5, 0.667, 0]])
>>> np_points
array([[0.   , 0.   , 0.   ],
       [1.   , 0.   , 0.   ],
       [0.5  , 0.667, 0.   ]])

我们在这里使用 numpy.ndarray,以便 PyVista 直接将底层 C 数组“指向”VTK。VTK 已经有 API 可以直接从 NumPy 读取 C 数组,并且由于 VTK 是用 C++ 编写的,从 Python 传输到 VTK 的所有内容都必须是 VTK 可以处理的格式。

如果您希望在 PyVista 中使用 VTK 对象,仍然可以这样做。事实上,使用 pyvista.wrap(),您甚至可以获取数据的类似 NumPy 的表示。例如:

code.matlab
>>> import pyvista as pv
>>> wrapped = pv.wrap(vtk_array)
>>> wrapped
pyvista_ndarray([[0.   , 0.   , 0.   ],
                 [1.   , 0.   , 0.   ],
                 [0.5  , 0.667, 0.   ]])

注意,当包装底层 VTK 数组时,我们实际上执行了数据的浅拷贝。换句话说,我们将指针从底层 C 数组传递到 numpy.ndarray,这意味着两个数组现在高效链接(在 NumPy 术语中,返回的数组是底层 VTK 数据的视图)。这意味着我们可以使用 NumPy 数组索引更改数组,并在“VTK 侧”修改它。

code.matlab
>>> wrapped[0, 0] = 10
>>> vtk_array.GetValue(0)
10.0

或者我们可以从 VTK 数组更改值并看到它反映在 NumPy 包装的数组中。让我们将值改回:

code.matlab
>>> vtk_array.SetValue(0, 0)
>>> wrapped[0, 0]
np.float64(0.0)

使用 Python 列表或元组

PyVista 支持使用 Python 序列(即 list 或 tuple),您可以使用嵌套列表的列表通过以下方式定义点:

code.matlab
>>> points = [[0, 0, 0], [1, 0, 0], [0.5, 0.667, 0]]

在用于创建网格的 PolyData 上下文中使用时,此列表将自动使用 NumPy 包装,然后传递给 VTK。这避免了任何循环开销,同时仍允许您使用原生 Python 类。

最后,让我们展示如何在这三种对象在 PyVista 几何类的上下文中使用。这里,我们创建一个只包含三个点的简单点网格:

code.matlab
>>> from_vtk = pv.PolyData(vtk_array)
>>> from_np = pv.PolyData(np_points)
>>> from_list = pv.PolyData(points)

这些点网格都包含三个点,并且实际上是相同的。让我们通过从网格访问底层点数组来展示这一点,该数组表示为 pyvista.pyvista_ndarray

code.matlab
>>> from_vtk.points
pyvista_ndarray([[0.   , 0.   , 0.   ],
                 [1.   , 0.   , 0.   ],
                 [0.5  , 0.667, 0.   ]])

并展示这些都相同

code.matlab
>>> assert np.array_equal(from_vtk.points, from_np.points)
>>> assert np.array_equal(from_vtk.points, from_list.points)
>>> assert np.array_equal(from_np.points, from_list.points)

最后,让我们使用 PyVista 的 pyvista.plot() 方法绘制这个(非常)简单的示例。让我们把它做成一个完整示例,以便您看到整个过程。

code.matlab
import pyvista as pv
points = [[0, 0, 0], [1, 0, 0], [0.5, 0.667, 0]]
mesh = pv.PolyData(points)
mesh.plot(show_bounds=True, cpos='xy', point_size=20)
Document Image
\[\]

我们稍后将介绍 PyVista 的数据类和属性,但现在我们已经展示了如何创建仅包含点的简单几何。要创建表面,我们必须指定几何的连接性,为此我们需要指定此表面的单元(或面)。